import base64
import io

import cv2
import numpy
from PIL import Image, ImageDraw, ImageFont


class ImageManager(object):
    """
    图片管理器
    """

    def __init__(self, scale):
        self._scale = scale
        self.default_char = "$@!#%^&*()zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLPOIUYTREWQ斯蒂芬森的"

    @staticmethod
    def bytes_to_array(image_bytes):
        """
        字节流转换数组
        :param image_bytes:
        :return:
        """
        image_array = numpy.frombuffer(image_bytes, dtype=numpy.uint8)
        return cv2.imdecode(image_array, cv2.IMREAD_COLOR)

    @staticmethod
    def bytes_to_str(image_bytes):
        """
        字节流转换字符串
        :param image_bytes:
        :return:
        """
        return base64.b64encode(image_bytes).decode('utf8')

    @staticmethod
    def array_to_bytes(image_array):
        """
        数组转换字节流
        :param image_array:
        :return:
        """
        data = cv2.imencode('.jpg', image_array)[1]
        return data.tobytes()

    def array_to_str(self, image_array):
        """
        数组转换字节流
        :param image_array:
        :return:
        """
        image_bytes = self.array_to_bytes(image_array)
        return self.bytes_to_str(image_bytes)

    @staticmethod
    def str_to_bytes(image_info):
        """
        字符串转字节流
        :param image_info:
        :return:
        """
        return base64.b64decode(image_info)

    def str_to_array(self, image_info):
        """
        字符串转数组
        :param image_info:
        :return:
        """
        image_bytes = self.bytes_to_str(image_info)
        return self.bytes_to_array(image_bytes)

    @staticmethod
    def read_image_bytes(image_path):
        """
        读取图片 字节流
        :param image_path:
        :return:
        """
        with open(image_path, 'rb') as f:
            image_bytes = f.read()
            return image_bytes

    @staticmethod
    def write_image_bytes(image_bytes, image_path):
        """
        字节流数据存储
        :param image_bytes:
        :param image_path:
        :return:
        """
        with open(image_path, 'wb') as f:
            f.write(image_bytes)
            return image_path

    def read_image(self, image_path, read_type="bytes"):
        """
        读取图片
        :param image_path:
        :param read_type:
        :return:
        """
        if read_type == "bytes":
            return self.read_image_bytes(image_path)
        elif read_type == "array":
            return cv2.imread(image_path)
        elif read_type == "str":
            image_bytes = self.read_image_bytes(image_path)
            return self.bytes_to_str(image_bytes)

    def save_image(self, image_info, image_path):
        """
        保存图片
        :param image_info:
        :param image_path:
        :return:
        """
        if isinstance(image_info, numpy.ndarray):
            cv2.imwrite(image_path, image_info)
        elif isinstance(image_info, str):
            image_bytes = self.str_to_bytes(image_info)
            self.write_image_bytes(image_bytes, image_path)
        elif isinstance(image_info, bytes):
            self.write_image_bytes(image_info, image_path)

    def conversion(self, import_img, export_img=None, input_char="", pix_distance=""):
        """
        图片转换
        :param pix_distance:
        :param import_img:
        :param export_img:
        :param input_char:
        :return:
        """
        img = Image.open(import_img)
        img_pix = img.load()
        img_width = img.size[0]
        img_height = img.size[1]
        canvas_array = numpy.ndarray((img_height * self._scale, img_width * self._scale, 3), numpy.uint8)
        canvas_array[:, :, :] = 255
        new_image = Image.fromarray(canvas_array)
        img_draw = ImageDraw.Draw(new_image)
        font = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 10)
        if input_char == "":
            char_list = list(self.default_char)
        else:
            char_list = list(input_char)

        if pix_distance == "清晰":
            pix_distance = 5
        else:
            pix_distance = 1

        pix_count = 0
        table_len = len(char_list)
        for y in range(img_height):
            for x in range(img_width):
                if x % pix_distance == 0 and y % pix_distance == 0:
                    img_draw.text((x * self._scale, y * self._scale), char_list[pix_count % table_len], img_pix[x, y],
                                  font)
                    pix_count += 1

        if export_img is not None:
            new_image.save(export_img)

    @staticmethod
    def image_frame(image_info, frame_info: dict):
        """
        图片画框
        :param image_info:
        :param frame_info:
        :return:
        """
        #  lineType == cv2.LINE_4、cv2.LINE_8、cv2.LINE_AA
        position = frame_info.get("position")
        color = frame_info.get("color", (0, 0, 255))
        thickness = frame_info.get("thickness", 1)
        # 画方框
        cv2.rectangle(image_info, position[0], position[1], color, thickness, lineType=cv2.LINE_4)
        # 画圆
        cv2.circle(image_info, (455, 128), 100, color, thickness, lineType=cv2.LINE_8)
        # 画线
        cv2.line(image_info, (455, 455), (999, 999), color, thickness, cv2.LINE_AA)
        # 画椭圆
        cv2.ellipse(image_info, (100, 100), (200, 200), 90, 0, 360, color, thickness)
        # 写字
        cv2.putText(image_info, "llllls", (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)


if __name__ == '__main__':
    image_man = ImageManager(1)
    image_array = image_man.read_image("img/1.jpg", read_type="bytes")
    image_man.save_image(image_array, "img/2.jpg")
    print(type(image_array))
    print("---------------------------")



